#include "BaseStmt.h"	
	
using namespace std;		

BaseStmt::BaseStmt()
{
	m_nBindInParamCounts =0;				
	m_nBindOutResultColumCounts =0;
	m_nCheckParam =0;
	m_nCheckResultColum =0;
	m_pStmt =NULL;
	m_pPrepare_meta_result =NULL;
	m_pBindIn =NULL;
	m_pBindOut =NULL;
	m_pInLength =NULL; 
}

BaseStmt::~BaseStmt()
{
	if(NULL != m_pBindIn)
	{
		delete[] m_pBindIn;
	}
	
	if(NULL != m_pBindOut)
	{
		delete[] m_pBindOut;
	}
	
	if(NULL != m_pInLength)
	{
		delete[] m_pInLength;
	}	
	
	if(0 !=mysql_stmt_close(m_pStmt))
	{
		fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_close(m_pStmt) failed");
		exit(0);
	}

}


int BaseStmt::GetStmt(MYSQL_STMT *pStmt)
{
	m_pStmt = pStmt;
	if(m_pStmt == NULL)
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "GetStmt() Failure");
		exit(0);
	}
	return 0;
}


int BaseStmt::Prepare(const char *query, unsigned long length)
{
	if(mysql_stmt_prepare(m_pStmt, query, length))
	{	
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_prepare() Failure");
		fprintf(stderr, " mysql_stmt_prepare(),SQL failed\n");
        fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
        exit(0);
	}

	//返回预处理语句中参数标记符的数目
	m_nBindInParamCounts = mysql_stmt_param_count(m_pStmt);//ParamCounts = 0 . 绑定到sql语句的参数是0个;没有参数输入在sql语句中.

	//如果不存在关于预处理查询的任何元信息，返回NULL。
	m_pPrepare_meta_result= mysql_stmt_result_metadata(m_pStmt);
	if(m_pPrepare_meta_result == NULL)
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "m_pPrepare_meta_result == NULL");
    	fprintf(stderr,"MYSQL_RES:prepare_meta_result is NULL or  Not the Insert \n");
	}
	else
	{
		//get the ResultParamCount 获取返回结果集的sql语句的返回的列的个数.
		m_nBindOutResultColumCounts= mysql_num_fields(m_pPrepare_meta_result);
	}
	
	//new BindIn
	if(0 !=m_nBindInParamCounts)
	{
		m_pBindIn =new(std::nothrow)  MYSQL_BIND[m_nBindInParamCounts];
		if(NULL == m_pBindIn)
		{
			LOG4CPLUS_ERROR(m_log.LogGet(), "m_pBindIn new memory failure");
			fprintf(stderr,"m_pBindIn new memory failure \n");
			exit(0);
		}
	
		m_pInLength =new(std::nothrow) long unsigned int [m_nBindInParamCounts];
		if(NULL == m_pInLength)
		{
			LOG4CPLUS_ERROR(m_log.LogGet(), "m_pBindInLength new memory failure");
			fprintf(stderr,"m_pBindInLength new memory failure \n");
			exit(0);			
		}
	
		memset(m_pBindIn,0,sizeof(MYSQL_BIND)*m_nBindInParamCounts);
		memset(m_pInLength,0,sizeof(long unsigned int)*m_nBindInParamCounts);
	}

	//new BindOut
	if(0 !=m_nBindOutResultColumCounts)
	{
		m_pBindOut =new(std::nothrow) MYSQL_BIND[m_nBindOutResultColumCounts];	
		if(NULL == m_pBindOut)
		{	
			LOG4CPLUS_ERROR(m_log.LogGet(), "m_pBindOut new memory failure");
			fprintf(stderr,"m_pBindOut new memory failure \n");
			exit(0);
		}
			
		memset(m_pBindOut,0,sizeof(MYSQL_BIND)*m_nBindOutResultColumCounts);
	}
	
	return 0;		
}


int BaseStmt::BindIn(int nParamPos,char *szParam, long unsigned int nParamLength)
{	
	m_pInLength[nParamPos-1]= strlen(szParam);
	
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_VAR_STRING;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(szParam);

	m_pBindIn[nParamPos-1].buffer_length= nParamLength;//buffer_length值指定了与mysql_stmt_bind_param()一起使用时的*buffer长度，或与mysql_stmt_bind_result()一起使用时能够提取到缓冲区内的最大数据。它指明了可保存在缓冲区内的最大数据

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= &m_pInLength[nParamPos-1];//对于输入参数数据绑定，“length”指向unsigned long变量，该变量指明了存储在*buffer中参数值的长度，供mysql_stmt_execute()使用。该变量指明了存储在*buffer中数据的实际字节数
	
	m_nCheckParam++;
			
	return 0;
}


int BaseStmt::BindIn(int nParamPos, short int *nParam, long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_SHORT;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(nParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;
	
	m_nCheckParam++;
			
	return 0;
}


int BaseStmt::BindIn(int nParamPos, int *nParam, long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_LONG;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(nParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;
	
	m_nCheckParam++;
			
	return 0;
}


int BaseStmt::BindIn(int nParamPos, long long int *nParam, long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_LONGLONG;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(nParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;

	m_nCheckParam++;
			
	return 0;
}	


int BaseStmt::BindIn(int nParamPos, float *fParam,  long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_FLOAT;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(fParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;
	
	m_nCheckParam++;

	return 0;
}

int BaseStmt::BindIn(int nParamPos, double *dParam, long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_DOUBLE;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(dParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;
	
	m_nCheckParam++;
			
	return 0;
}

/*
int BaseStmt::BindIn(int nParamPos, MYSQL_TIME &tParam, long unsigned int nParamLength)
{		
	m_pBindIn[nParamPos-1].buffer_type= MYSQL_TYPE_TIMESTAMP;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindIn[nParamPos-1].buffer= (char*)(tParam);

	m_pBindIn[nParamPos-1].is_null= 0;

 	m_pBindIn[nParamPos-1].length= 0;
	
	m_nCheckParam++;
			
	return 0;
}
*/

int BaseStmt::BindOut(int nResPos, char *szRes, long unsigned int nBufLength)
{	
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_VAR_STRING;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (char *)szRes;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;//buffer_length值指定了与mysql_stmt_bind_param()一起使用时的*buffer长度，或与mysql_stmt_bind_result()一起使用时能够提取到缓冲区内的最大数据。它指明了可保存在缓冲区内的最大数据

	m_pBindOut[nResPos-1].is_null= 0;

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;
	
}


int BaseStmt::BindOut(int nResPos, short int *nParam, long unsigned int nBufLength)
{
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_SHORT;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (short int *)nParam;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;

	m_pBindOut[nResPos-1].is_null=  0;

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;
	
}

int BaseStmt::BindOut(int nResPos, int *nParam, long unsigned int nBufLength)
{	
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_LONG;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (int *)nParam;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;

	m_pBindOut[nResPos-1].is_null=  0;

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;	
}

int BaseStmt::BindOut(int nResPos,long long int *nParam, long unsigned int nBufLength)
{	
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_LONGLONG;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (long long int *)nParam;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;

	m_pBindOut[nResPos-1].is_null= 0;

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;	
}

int BaseStmt::BindOut(int nResPos, float *fParam,  long unsigned int nBufLength)
{	
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_FLOAT;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (float *)fParam;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;

	m_pBindOut[nResPos-1].is_null= 0;//对于输出，如果从语句返回的结果集列值为NULL，当获取了行后，该值将被设为“真”。

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;	
}

int BaseStmt::BindOut(int nResPos, double *dParam,  long unsigned int nBufLength)
{	
	m_pBindOut[nResPos-1].buffer_type= MYSQL_TYPE_DOUBLE;//buffer_type指明了与语句参数捆绑的值类型。对于输出，它指明了你希望从结果缓冲收到的值类型。

	m_pBindOut[nResPos-1].buffer= (double *)dParam;

	m_pBindOut[nResPos-1].buffer_length= nBufLength;

	m_pBindOut[nResPos-1].is_null=  0;

 	m_pBindOut[nResPos-1].length= &nBufLength;
	
	m_nCheckResultColum++;

	return 0;	
}

int BaseStmt::Excute()
{	

	if(m_nCheckParam != m_nBindInParamCounts)
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_bind_param_counts failed");
		fprintf(stderr, " mysql_stmt_bind_param_counts failed\n");	
		exit(0);
	}

	if(m_nCheckResultColum != m_nBindOutResultColumCounts)
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_bind_result_colum_counts failed");
		fprintf(stderr, " mysql_stmt_bind_result_colum_counts failed\n");	
		exit(0);
	}

	if(0 != m_nBindInParamCounts)
	{
		if (mysql_stmt_bind_param(m_pStmt, m_pBindIn))
		{
			LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_bind_param() failed");
			fprintf(stderr, " mysql_stmt_bind_param() failed\n");
			fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
 			exit(0);
		}
	}
		
	if(0 != m_nBindOutResultColumCounts)
	{
		if (mysql_stmt_bind_result(m_pStmt, m_pBindOut))
			{
				LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_bind_result() failed");
    			fprintf(stderr, " mysql_stmt_bind_result() failed\n");
    			fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
    			exit(0);
			}
	}	

	if (mysql_stmt_execute(m_pStmt))
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_execute() failed");
		fprintf(stderr, " mysql_stmt_execute() failed\n");
		fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
		exit(0);
	}	

	
	
	/*Now buffer all results to client*/
	
	if (mysql_stmt_store_result(m_pStmt))
	{
		LOG4CPLUS_ERROR(m_log.LogGet(), "mysql_stmt_store_result() failed");
  		fprintf(stderr, " mysql_stmt_store_result() failed\n");
  		fprintf(stderr, " %s\n", mysql_stmt_error(m_pStmt));
  		exit(0);
	}

    printf(" Number of rows: %lu\n",(long unsigned)mysql_stmt_num_rows(m_pStmt));
	return 0;
}
	
int BaseStmt::Fetch()
{				
 	return mysql_stmt_fetch(m_pStmt);
}






